TypeScript 中的设计模式实现

概述

设计模式是软件开发中解决常见问题的可重用解决方案。TypeScript 作为一种强类型语言,结合了 JavaScript 的灵活性和静态类型的安全性,非常适合实现各种设计模式。本教程将介绍如何在 TypeScript 中实现一些常见的设计模式,包括创建型、结构型和行为型模式。

1. 创建型模式

1.1 单例模式

单例模式确保一个类只有一个实例,并提供一个全局访问点。

理论解释: 单例模式适用于需要全局唯一实例的场景,例如配置管理、日志记录等。

代码示例:

class Singleton {
    private static instance: Singleton;

    private constructor() {
        // 私有构造函数,防止外部实例化
    }

    public static getInstance(): Singleton {
        if (!Singleton.instance) {
            Singleton.instance = new Singleton();
        }
        return Singleton.instance;
    }

    public someMethod(): void {
        console.log("Singleton method called");
    }
}

// 使用单例
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();

console.log(instance1 === instance2); // true
instance1.someMethod(); // Singleton method called

实践练习: 尝试创建一个配置管理类,使用单例模式确保全局只有一个配置实例。

1.2 工厂模式

工厂模式提供了一种创建对象的方式,而不需要指定具体的类。

理论解释: 工厂模式适用于需要根据不同条件创建不同对象的场景,例如根据用户输入创建不同的 UI 组件。

代码示例:

interface Product {
    operation(): void;
}

class ConcreteProductA implements Product {
    operation(): void {
        console.log("ConcreteProductA operation");
    }
}

class ConcreteProductB implements Product {
    operation(): void {
        console.log("ConcreteProductB operation");
    }
}

class Creator {
    public factoryMethod(type: string): Product {
        switch (type) {
            case "A":
                return new ConcreteProductA();
            case "B":
                return new ConcreteProductB();
            default:
                throw new Error("Invalid product type");
        }
    }
}

// 使用工厂
const creator = new Creator();
const productA = creator.factoryMethod("A");
productA.operation(); // ConcreteProductA operation

实践练习: 创建一个简单的工厂类,根据用户输入创建不同的形状对象(如圆形、矩形)。

2. 结构型模式

2.1 装饰器模式

装饰器模式允许动态地为对象添加功能,而不改变其结构。

理论解释: 装饰器模式适用于需要在不修改现有代码的情况下扩展对象功能的场景,例如日志记录、性能监控等。

代码示例:

interface Component {
    operation(): void;
}

class ConcreteComponent implements Component {
    operation(): void {
        console.log("ConcreteComponent operation");
    }
}

class Decorator implements Component {
    private component: Component;

    constructor(component: Component) {
        this.component = component;
    }

    operation(): void {
        console.log("Decorator additional behavior");
        this.component.operation();
    }
}

// 使用装饰器
const component = new ConcreteComponent();
const decoratedComponent = new Decorator(component);
decoratedComponent.operation(); // Decorator additional behavior, ConcreteComponent operation

实践练习: 创建一个简单的装饰器类,为现有组件添加日志记录功能。

2.2 适配器模式

适配器模式允许将一个类的接口转换为客户端期望的另一个接口。

理论解释: 适配器模式适用于需要复用现有类,但其接口不符合新系统要求的场景,例如将旧的 API 适配到新的系统中。

代码示例:

interface Target {
    request(): void;
}

class Adaptee {
    specificRequest(): void {
        console.log("Adaptee specific request");
    }
}

class Adapter implements Target {
    private adaptee: Adaptee;

    constructor(adaptee: Adaptee) {
        this.adaptee = adaptee;
    }

    request(): void {
        this.adaptee.specificRequest();
    }
}

// 使用适配器
const adaptee = new Adaptee();
const adapter = new Adapter(adaptee);
adapter.request(); // Adaptee specific request

实践练习: 创建一个适配器类,将一个旧的 API 适配到新的系统中。

3. 行为型模式

3.1 观察者模式

观察者模式定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会收到通知并自动更新。

理论解释: 观察者模式适用于需要实现事件驱动的场景,例如用户界面中的事件处理、消息通知等。

代码示例:

interface Observer {
    update(subject: Subject): void;
}

class Subject {
    private observers: Observer[] = [];

    attach(observer: Observer): void {
        this.observers.push(observer);
    }

    detach(observer: Observer): void {
        const index = this.observers.indexOf(observer);
        if (index !== -1) {
            this.observers.splice(index, 1);
        }
    }

    notify(): void {
        for (const observer of this.observers) {
            observer.update(this);
        }
    }

    public state: number = 0;
}

class ConcreteObserver implements Observer {
    update(subject: Subject): void {
        console.log(`Observer received state: ${subject.state}`);
    }
}

// 使用观察者模式
const subject = new Subject();
const observer1 = new ConcreteObserver();
const observer2 = new ConcreteObserver();

subject.attach(observer1);
subject.attach(observer2);

subject.state = 1;
subject.notify(); // Observer received state: 1, Observer received state: 1

实践练习: 创建一个简单的观察者模式实现,模拟用户界面中的事件处理。

3.2 策略模式

策略模式定义了一系列算法,并将每个算法封装起来,使它们可以互换。

理论解释: 策略模式适用于需要在运行时选择不同算法的场景,例如排序算法、支付方式等。

代码示例:

interface Strategy {
    execute(a: number, b: number): number;
}

class AddStrategy implements Strategy {
    execute(a: number, b: number): number {
        return a + b;
    }
}

class SubtractStrategy implements Strategy {
    execute(a: number, b: number): number {
        return a - b;
    }
}

class Context {
    private strategy: Strategy;

    constructor(strategy: Strategy) {
        this.strategy = strategy;
    }

    setStrategy(strategy: Strategy): void {
        this.strategy = strategy;
    }

    executeStrategy(a: number, b: number): number {
        return this.strategy.execute(a, b);
    }
}

// 使用策略模式
const context = new Context(new AddStrategy());
console.log(context.executeStrategy(3, 4)); // 7

context.setStrategy(new SubtractStrategy());
console.log(context.executeStrategy(3, 4)); // -1

实践练习: 创建一个策略模式实现,模拟不同支付方式的选择。

总结

本教程介绍了 TypeScript 中几种常见的设计模式,包括创建型、结构型和行为型模式。通过理论解释、代码示例和实践练习,帮助初学者理解和掌握这些设计模式在 TypeScript 中的实现。设计模式是软件开发中的重要工具,掌握它们将有助于编写更灵活、可维护的代码。

进一步学习

  • 深入学习其他设计模式,如代理模式、命令模式、状态模式等。
  • 探索 TypeScript 中的高级类型和泛型,进一步提升代码的灵活性和可维护性。
  • 研究 TypeScript 在实际项目中的应用,如 React、Node.js 等。

通过不断实践和学习,你将能够更好地应用 TypeScript 和设计模式,构建出高效、可扩展的软件系统。